package se.jocke.nb.log.ui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListModel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ColorComboBox;
import se.jocke.nb.log.model.LogViewFilter;

final class LogViewPanel extends javax.swing.JPanel {

    private final LogViewOptionsPanelController controller;

    private static final Logger LOG = Logger.getLogger(LogViewPanel.class.getName());

    LogViewPanel(LogViewOptionsPanelController controller) {
        this.controller = controller;
        initComponents();
        filterList.setCellRenderer(new LogViewFilterListCellRenderer());
        filterList.setModel(new DefaultListModel());
    }

    public static final class LogViewFilterListCellRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Component listCellRendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            JLabel label = (JLabel) listCellRendererComponent;
            label.setText(((LogViewFilter) value).getName());
            return listCellRendererComponent;
        }

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        filterList = new javax.swing.JList();
        jLabel1 = new javax.swing.JLabel();
        removeButton = new javax.swing.JButton();
        addButton = new javax.swing.JButton();
        upButton = new javax.swing.JButton();
        downButton = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        fontTextField = new javax.swing.JTextField();
        changeFontButton = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        foregroundComboBox = new ColorComboBox();
        jLabel4 = new javax.swing.JLabel();
        backgroundComboBox = new ColorComboBox();
        jLabel5 = new javax.swing.JLabel();
        patternTextField = new javax.swing.JTextField();
        regexCheckBox = new javax.swing.JCheckBox();

        filterList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        filterList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                filterListValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(filterList);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.jLabel1.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(removeButton, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.removeButton.text")); // NOI18N
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(addButton, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.addButton.text")); // NOI18N
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        upButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/se/jocke/nb/log/ui/up.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(upButton, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.upButton.text")); // NOI18N
        upButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                upButtonActionPerformed(evt);
            }
        });

        downButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/se/jocke/nb/log/ui/down.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(downButton, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.downButton.text")); // NOI18N
        downButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                downButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.jLabel2.text")); // NOI18N

        fontTextField.setText(org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.fontTextField.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(changeFontButton, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.changeFontButton.text")); // NOI18N
        changeFontButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changeFontButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.jLabel3.text")); // NOI18N

        foregroundComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                foregroundComboBoxActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.jLabel4.text")); // NOI18N

        backgroundComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                backgroundComboBoxActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.jLabel5.text")); // NOI18N

        patternTextField.setText(org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.patternTextField.text")); // NOI18N
        patternTextField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                patternTextFieldActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(regexCheckBox, org.openide.util.NbBundle.getMessage(LogViewPanel.class, "LogViewPanel.regexCheckBox.text")); // NOI18N
        regexCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                regexCheckBoxActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(upButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(downButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(addButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(removeButton))
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 294, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jLabel1)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel3)
                            .addComponent(jLabel4)
                            .addComponent(jLabel5))
                        .addGap(21, 21, 21)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(fontTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 297, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(changeFontButton))
                            .addComponent(foregroundComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(backgroundComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(patternTextField)))
                    .addComponent(regexCheckBox))
                .addContainerGap(18, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addGap(4, 4, 4)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel5)
                            .addComponent(patternTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(16, 16, 16)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel2)
                            .addComponent(fontTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(changeFontButton))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel3)
                            .addComponent(foregroundComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabel4)
                            .addComponent(backgroundComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(jScrollPane1))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(removeButton)
                    .addComponent(addButton)
                    .addComponent(upButton)
                    .addComponent(downButton)
                    .addComponent(regexCheckBox))
                .addContainerGap(81, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void filterListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_filterListValueChanged
        LogViewFilter filter = (LogViewFilter) filterList.getSelectedValue();
        if (filter != null) {
            filterChanged(filter);
        }
    }//GEN-LAST:event_filterListValueChanged

    private void filterChanged(LogViewFilter filter) {
        controller.changed();
        patternTextField.setText(filter.getPattern());
        fontTextField.setText(filter.getFont().getFontName());
        fontTextField.setFont(filter.getFont());

        ColorComboBox.class.cast(foregroundComboBox).setSelectedColor(filter.getForegroundColor());
        ColorComboBox.class.cast(backgroundComboBox).setSelectedColor(filter.getBackgroundColor());
        patternTextField.setEditable(!filter.getName().equalsIgnoreCase(LogViewFilter.DEFAULT_FILTER_NAME));
    }

    private void foregroundComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_foregroundComboBoxActionPerformed
        LogViewFilter filter = (LogViewFilter) filterList.getSelectedValue();

        if (filter != null) {
            Color selectedColor = ColorComboBox.class.cast(foregroundComboBox).getSelectedColor();
            if (selectedColor != null) {
                filter.setForegroundColor(selectedColor);
                filterChanged(filter);
            } else {
                LOG.info("No color selected");
            }
        } else {
            LOG.info("No filter selected");
        }
    }//GEN-LAST:event_foregroundComboBoxActionPerformed

    private void backgroundComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backgroundComboBoxActionPerformed
        LogViewFilter filter = (LogViewFilter) filterList.getSelectedValue();

        if (filter != null) {
            Color selectedColor = ColorComboBox.class.cast(backgroundComboBox).getSelectedColor();
            if (selectedColor != null) {
                filter.setBackgroundColor(selectedColor);
                filterChanged(filter);
            } else {
                LOG.info("No color selected");
            }
        } else {
            LOG.info("No filter selected");
        }
    }//GEN-LAST:event_backgroundComboBoxActionPerformed

    private void changeFontButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changeFontButtonActionPerformed
        LogViewFilter filter = (LogViewFilter) filterList.getSelectedValue();
        if (filter != null) {

            PropertyEditor pe = PropertyEditorManager.findEditor(Font.class);
            DialogDescriptor dd = new DialogDescriptor(
                    pe.getCustomEditor(),
                    "Choose font" // NOI18N
            );

            DialogDisplayer.getDefault().createDialog(dd).setVisible(true);
            if (dd.getValue() == DialogDescriptor.OK_OPTION) {
                Font font = (Font) pe.getValue();
                filter.setFont(font);
                filterChanged(filter);
            }
        }
    }//GEN-LAST:event_changeFontButtonActionPerformed

    private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
        String txt = "Name: ";
        String title = "Create new filter";
        NotifyDescriptor.InputLine input = new NotifyDescriptor.InputLine(txt, title);
        input.setInputText("Name");
        Object result = DialogDisplayer.getDefault().notify(input);

        if (result != NotifyDescriptor.OK_OPTION) {
            return;
        }

        String name = input.getInputText();

        if (name == null || name.isEmpty()) {
            return;
        }

        LogViewFilter newFilter = new LogViewFilter();
        newFilter.setName(name);
        LogViewFilter defaultFilter = controller.findDefault();
        newFilter.setBackgroundColor(defaultFilter.getBackgroundColor());
        newFilter.setForegroundColor(defaultFilter.getForegroundColor());
        newFilter.setPattern("text");
        newFilter.setFont(defaultFilter.getFont());
        DefaultListModel<LogViewFilter> model = (DefaultListModel<LogViewFilter>) filterList.getModel();
        model.addElement(newFilter);


    }//GEN-LAST:event_addButtonActionPerformed

    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
        int selectedIndex = filterList.getSelectedIndex();

        if (selectedIndex >= 0) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) filterList.getModel();
            listModel.remove(selectedIndex);
        }

    }//GEN-LAST:event_removeButtonActionPerformed

    private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
        int selectedIndex = filterList.getSelectedIndex();

        if (selectedIndex >= 1 && selectedIndex < filterList.getModel().getSize() - 1) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) filterList.getModel();
            listModel.add(selectedIndex - 1, listModel.remove(selectedIndex));
        }
    }//GEN-LAST:event_upButtonActionPerformed

    private void downButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downButtonActionPerformed
        int selectedIndex = filterList.getSelectedIndex();

        if (selectedIndex >= 0 && selectedIndex < filterList.getModel().getSize() - 2) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) filterList.getModel();
            listModel.add(selectedIndex + 1, listModel.remove(selectedIndex));
        }
    }//GEN-LAST:event_downButtonActionPerformed

    private void regexCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_regexCheckBoxActionPerformed
        controller.changed();

        int selectedIndex = filterList.getSelectedIndex();

        if (selectedIndex >= 0) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) filterList.getModel();
            listModel.get(selectedIndex).setRegex(regexCheckBox.isSelected());
        }
    }//GEN-LAST:event_regexCheckBoxActionPerformed

    private void patternTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_patternTextFieldActionPerformed
        controller.changed();
        int selectedIndex = filterList.getSelectedIndex();
        if (selectedIndex >= 0) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) filterList.getModel();
            listModel.get(selectedIndex).setPattern(patternTextField.getText());
        }
    }//GEN-LAST:event_patternTextFieldActionPerformed

    void load() {
        DefaultListModel<LogViewFilter> listModel = new DefaultListModel<LogViewFilter>();
        List<LogViewFilter> loadLogViewFilters = controller.loadLogViewFilters();
        for (LogViewFilter logViewFilter : loadLogViewFilters) {
            listModel.addElement(logViewFilter);
        }
        filterList.setModel(listModel);

    }

    void store() {
        ListModel model = filterList.getModel();
        if (model instanceof DefaultListModel) {
            DefaultListModel<LogViewFilter> listModel = (DefaultListModel<LogViewFilter>) model;
            List<LogViewFilter> logViewFilters = new ArrayList<LogViewFilter>(Math.max(1, listModel.size()));
            for (int i = 0; i < listModel.size(); i++) {
                final LogViewFilter filter = listModel.getElementAt(i);
                if (!filter.isDefault()) {
                    filter.setWeight(i);
                }
                logViewFilters.add(filter);
            }
            controller.storeLogViewFilters(logViewFilters);
        }
    }

    boolean valid() {
        // TODO check whether form is consistent and complete
        return true;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addButton;
    private javax.swing.JComboBox backgroundComboBox;
    private javax.swing.JButton changeFontButton;
    private javax.swing.JButton downButton;
    private javax.swing.JList filterList;
    private javax.swing.JTextField fontTextField;
    private javax.swing.JComboBox foregroundComboBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField patternTextField;
    private javax.swing.JCheckBox regexCheckBox;
    private javax.swing.JButton removeButton;
    private javax.swing.JButton upButton;
    // End of variables declaration//GEN-END:variables
}
